﻿/**
 * ImageHandler
 *
 * ImageHandler can move, rotate or resize ImageHolder objects.
 *
 * ImageHandler is part of the sample application for the presentation on Flash ActionScript Cafe's 2nd conference.
 * 
 *
 * @author: Han Sanghun (http://hangunsworld.com, hanguns@gmail.com)
 * @created: 2007 04 00
 * @last modified: 2008 05 24
 */
 
package conf{
	
	import comp.cpMaker;
	
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.ui.*;
	import flash.utils.Timer;
	
	
	public class ImageHandler extends MovieClip{
		
		private var _root:MovieClip;
		private var _parent:MovieClip;
		
		
		// 회전시 사용할 변수
		private var olda:Number;
		private var oria:Number;
		
		private var target:MovieClip;
		private var image:Bitmap;
		
		private var bound:DisplayObject; // 드래그 영역 제한 타겟
		private var bound_rect:Rectangle; // 드래그 영역
		
		// 크기 정보
		private var originWidth:Number;
		private var originHeight:Number;
		private var minWidth:Number = 20;
		private var minHeight:Number = 20;
		private var maxWidth:Number;
		private var maxHeight:Number;
		
		private var proportion:Number;
		
		private var difx:Number;
		private var dify:Number;
		
		
		private var cm:ContextMenu;
		
		public var mc:MovieClip;
		
		public var _pa:cpMaker;
		public var _directPos:String;
		/**
		 * Constructor function
		 */
		public function ImageHandler(pa:*, directPos:String){
			_directPos = directPos;
			_pa = pa.oCpMaker;
			
			if(directPos=="hgL") {
				mc = _pa._ih as MovieClip;				
			} else if(directPos=="hgR"){
				mc = _pa._ihR as MovieClip;				
			}
			
			
			
			mc.visible = false;
			
			mc.rotate_mc.buttonMode = mc.size_mc.buttonMode = mc.move_mc.buttonMode = mc.rect_mc.buttonMode = true;
			
			// 사각 영역
			mc.rect_mc.addEventListener(MouseEvent.MOUSE_DOWN, rectDragStart);
			// 이동
			mc.move_mc.addEventListener(MouseEvent.MOUSE_DOWN, rectDragStart);
			
			// 크기
			mc.size_mc.addEventListener(MouseEvent.MOUSE_DOWN, sizeDragStart);
			
			// 회전
			mc.rotate_mc.addEventListener(MouseEvent.MOUSE_DOWN, rotateDragStart);
			mc.rotate_mc.addEventListener(MouseEvent.DOUBLE_CLICK, rotateReset);
			mc.rotate_mc.doubleClickEnabled = true;
			
			// 메뉴
			mc.menu_mc.visible = false;
			
			
			addEventListener(Event.ADDED_TO_STAGE, addedListener);
			
		}// end constructor
		
		
		
		
		
		/**
		 * 타겟 ImageHolder 객체 선택하기
		 *
		 * @param pTarget 타겟 무비
		 */
		public function setTarget(pTarget:MovieClip=null):void{
			
			if(pTarget == null){
				
				// 타겟이 지정되지 않으면 선택 해제
				mc.visible = false;
				target = null;
				
			}else{
				
				// 타겟이 지정된 경우
				target = pTarget;
				image = target.image;
				
				maxWidth = target.maxWidth;
				maxHeight = target.maxHeight;
				
				var w:uint = image.width; 
				var h:uint = image.height;
				
//				var w:uint = target.width; 
//				var h:uint = target.height;
				
				
				var w2:uint = w / 2;
				var h2:uint = h / 2;
				
				
				
				
				mc.x = target.x;
				mc.y = target.y;
				mc.rotation = target.rotation;
				
				// 사각형
				mc.rect_mc.width = w;
				mc.rect_mc.height = h;
				
				// 이동
				mc.move_mc.x = - w2;
				mc.move_mc.y = - h2;
				
				// 회전
				mc.rotate_mc.x = -w2;
				mc.rotate_mc.y = h2;
				
				// 크기
				mc.size_mc.x = w2;
				mc.size_mc.y = h2;
				
				// 메뉴
				/*menu_mc.x = w2;
				menu_mc.y = -h2;*/
				
				// 대쉬
				resizeDash();
				
				mc.visible = true;
				
			}// end if [target]
			
		}// end setTarget
		
		
		
		/**
		 * 점선의 크기를 조정
		 */
		private function resizeDash():void{
			
			var w:Number = mc.rect_mc.width/2;
			var h:Number = mc.rect_mc.height/2;
			
			mc.dash_mc.dash1.x = -w;
			mc.dash_mc.dash1.y = -h;
			mc.dash_mc.dash2.x = w;
			mc.dash_mc.dash2.y = h;
			
			mc.dash_mc.mask_mc.x = -w - .5;
			mc.dash_mc.mask_mc.y = -h - .5;
			mc.dash_mc.mask_mc.width = w*2 + 1;
			mc.dash_mc.mask_mc.height = h*2 + 1;
			
			mc.dash_mc.x = mc.rect_mc.x;
			mc.dash_mc.y = mc.rect_mc.y;
			
		}// end resizeDash
		
		
		/************************************************************************************
		                                                                    SETTER
		************************************************************************************/
		public function set resizable(pStat:Boolean){
			mc.size_mc.visible = pStat;
		}// end SET allowResize
		
		public function set rotatable(pStat:Boolean){
			mc.rotate_mc.visible = pStat;
		}// end SET allowRotate
		
		public function set movable(pStat:Boolean){
			mc.move_mc.visible = pStat;
		}// end SET allowMove
		/************************************************************************************
		                                                                    SETTER
		************************************************************************************/
		
		
		
		/************************************************************************************
		                                                       이동 / 회전/ 리사이즈 / 메뉴
		************************************************************************************/
		/**
		 * 이동 시작
		 */
		private function rectDragStart(e:MouseEvent):void{
			

			
			stage.addEventListener(MouseEvent.MOUSE_UP, rectDragStop);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, rectDraging);
			trace('rectDragStart x : '+ mc.x + ", mc y : " + mc.y);
			difx = mc.x - _parent.mouseX;
			dify = mc.y - _parent.mouseY;
			
			// 왼쪽, 오른쪽 에디터 위치를 가르쳐 줘서 레이어 순위를 바꿈
			_pa.chgEdtLayerDept(_directPos);
		}// end rectDragStart
		
		/**
		 * 이동중
		 */
		private function rectDraging(e:MouseEvent):void{
			
			trace('rectDraging x : '+ x + ", difx : " +difx);
			mc.x = _parent.mouseX + difx;
			mc.y = _parent.mouseY + dify;
			
			target.x = mc.x;
			target.y = mc.y;
			
			e.updateAfterEvent();
			
		}// end rectDraging
		
		/**
		 * 이동 종료
		 */
		private function rectDragStop(e:MouseEvent):void{
			
			trace('rectDragStop x : '+ mc.x + ", mc y : " + mc.y);
			
			stage.removeEventListener(MouseEvent.MOUSE_UP, rectDragStop);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, rectDraging);
			
			_pa.setSelectedPage(cfv.ISEDITING, true);
			
		}// end rectDragStop
		
		
		
		
		/**
		 * 리사이즈 시작
		 */
		private function sizeDragStart(evt:MouseEvent):void{
			
			// 이미지 비율
			proportion = image.width / image.height;
			
			stage.addEventListener(MouseEvent.MOUSE_MOVE, sizeDragging);
			stage.addEventListener(MouseEvent.MOUSE_UP, sizeDragStop);
			
		}// end sizeDragStart
		
		/**
		 * 리사이즈중
		 */
		private function sizeDragging(e:MouseEvent):void{
			
			var xp:Number = mc.mouseX;
			var yp:Number = mc.mouseY;
			
			if(e.shiftKey){
				
				// 쉬프트 키를 누른 상태, 가로세로 비율 유지
				if((xp - mc.size_mc.x) < (yp - mc.size_mc.y)){
					
					// 가로방향 기준
					xp = Math.max(Math.max(mc.move_mc.x + minWidth, (mc.move_mc.y + minHeight) * proportion), xp);
					xp = Math.min(Math.min(mc.move_mc.x + maxWidth, (mc.move_mc.y + maxWidth) * proportion), xp);
					yp = xp / proportion;
					
				}else{
					
					// 세로방향 기준
					yp = Math.max(Math.max(mc.move_mc.y + minHeight, (mc.move_mc.x + minWidth) / proportion), yp);
					yp = Math.min(Math.min(mc.move_mc.y + maxHeight, (mc.move_mc.x + maxHeight) / proportion), yp);
					xp = yp * proportion;
					
				}
				
			}else{
				
				// 쉬프트 키 없을 때
				xp = Math.min(Math.max(mc.move_mc.x + minWidth, xp), mc.move_mc.x + maxWidth);
				yp = Math.min(Math.max(mc.move_mc.y + minHeight, yp), mc.move_mc.y + maxHeight);
				
			}// end if [shiftKey]
			
			mc.size_mc.x = xp;
			mc.size_mc.y = yp;
			mc.rect_mc.width = xp - mc.move_mc.x;
			mc.rect_mc.height = yp - mc.move_mc.y;
			mc.rect_mc.x = mc.move_mc.x + mc.rect_mc.width/2;
			mc.rect_mc.y = mc.move_mc.y + mc.rect_mc.height/2;
			//menu_mc.x = xp;
			
			mc.rotate_mc.y = yp;
			
			image.width = mc.rect_mc.width;
			image.height = mc.rect_mc.height;
			
			
			resizeDash();
			
			e.updateAfterEvent();
			
		}// end sizeDragging
		
		/**
		 * 리사이즈 종료
		 */
		private function sizeDragStop(e:MouseEvent):void{
			
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, sizeDragging);
			stage.removeEventListener(MouseEvent.MOUSE_UP, sizeDragStop);
			
			var tx:Number = mc.move_mc.x + image.width/2;
			var ty:Number = mc.move_mc.y + image.height/2;
			
			var pt1:Point = new Point(image.x, image.y);
			var gpt1:Point = mc.localToGlobal(pt1);
			
			// 이미지 가운데 정렬하기
			image.x = -image.width/2;
			image.y = -image.height/2;
			
			// ImageHolder 위치 보정
			var pt2:Point = new Point(image.x, image.y);
			var gpt2:Point = mc.localToGlobal(pt2);
			
			
			target.x = target.x - (gpt2.x - gpt1.x);
			target.y = target.y - (gpt2.y - gpt1.y);
			
			var dx:Number = mc.rect_mc.width/2;
			var dy:Number = mc.rect_mc.height/2;
			
			mc.dash_mc.x = mc.rect_mc.x = 0;
			mc.dash_mc.y = mc.rect_mc.y = 0;
			mc.move_mc.x = -dx;
			mc.move_mc.y = -dy;
			mc.size_mc.x = dx;
			mc.size_mc.y = dy;
			mc.rotate_mc.x = -dx;
			mc.rotate_mc.y = dy;
			/*menu_mc.x = dx;
			menu_mc.y = -dy;*/
			
			mc.x = target.x;
			mc.y = target.y;
			
			_pa.setSelectedPage(cfv.ISEDITING, true);
		}// end sizeDragStop
		
		
		
		
		/**
		 * 회전 핸들 더블클릭하면 회전 초기화
		 */
		private function rotateReset(e:MouseEvent):void{
			mc.rotation = 0;
			target.rotation = 0;
			rotation = 0;
			
		}// end rotateReset
		
		/**
		 * 회전 시작
		 */
		private function rotateDragStart(e:MouseEvent):void{
			
			olda = Math.atan2(mc.mouseY, mc.mouseX)*180/Math.PI;
			oria = olda;
			
			stage.addEventListener(MouseEvent.MOUSE_MOVE, rotateDragging);
			stage.addEventListener(MouseEvent.MOUSE_UP, rotateDragStop);
			
		}// end rotateDragStart
		
		/**
		 * 회전중
		 */
		private function rotateDragging(e:MouseEvent):void{
			trace("mc.rotation : " + mc.rotation + ", rotation : " + rotation);
			mc.rotation += olda - oria;
			target.rotation = mc.rotation;
			olda = Math.atan2(mc.mouseY, mc.mouseX)*180/Math.PI;
			
			e.updateAfterEvent();
			
		}// end rotateDragging
		
		/**
		 * 회전 종료
		 */
		private function rotateDragStop(e:MouseEvent):void{
			
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, rotateDragging);
			stage.removeEventListener(MouseEvent.MOUSE_UP, rotateDragStop);
			_pa.setSelectedPage(cfv.ISEDITING, true);
			
		}// end rotateDragStop
		
		/**
		 * 메뉴 무비 클릭 이벤트 핸들러
		 */
		/*private function menuClick(evt:MouseEvent):void{
			
			var pnt:Point = new Point(menu_mc.x, menu_mc.y);
			var _parent:MovieClip = parent as MovieClip;
			var pnt2:Point = localToGlobal(pnt);
			_root.popupManager.showMenu(target, pnt2);
			
		}// end menuClick*/
		/************************************************************************************
		                                                       이동 / 회전/ 리사이즈 / 메뉴
		************************************************************************************/
		
		
		
		/**
		 * 스테이지에 애드되면, 초기화 실행
		 */
		private function addedListener(evt:Event):void{
			
			removeEventListener(Event.ADDED_TO_STAGE, addedListener);
			
			_root = root as MovieClip;			
			_parent = parent as MovieClip;
			
			
			// 컨텍스트 메뉴 설정
			cm = new ContextMenu();
			cm.hideBuiltInItems();
			
			var cmi:ContextMenuItem;
			cmi = new ContextMenuItem(" + Bring to Front(image handler)");
			cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, cmiListener);
			cm.customItems.push(cmi);
			
			cmi = new ContextMenuItem(" + Bring Forward");
			cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, cmiListener);
			cm.customItems.push(cmi);
			
			cmi = new ContextMenuItem(" + Send Backward");
			cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, cmiListener);
			cm.customItems.push(cmi);
			
			cmi = new ContextMenuItem(" + Send to Back");
			cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, cmiListener);
			cm.customItems.push(cmi);
			
			cmi = new ContextMenuItem(" + Deselect", true);
			cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, cmiListener);
			cm.customItems.push(cmi);
			
			cmi = new ContextMenuItem(" + Reset", true);
			cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, cmiListener);
			cm.customItems.push(cmi);
			
			cmi = new ContextMenuItem(" + Remove");
			cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, cmiListener);
			cm.customItems.push(cmi);
			
			cmi = new ContextMenuItem(" + Remove All");
			cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, cmiListener);
			cm.customItems.push(cmi);
			
			mc.contextMenu = cm;
			
		}// end addedListener
		
		
		/**
		 * 컨텍스트 메뉴 선택 이벤트리스너
		 */
		private function cmiListener(e:ContextMenuEvent):void{
			
			var cmi:ContextMenuItem = e.target as ContextMenuItem;
			var str:String = cmi.caption;
			
			//var cont_sp:Sprite = _root.cont_sp;
			var cont_sp:Sprite = _parent.cont_sp;
			
			
			switch(str){
				
				case " + Bring to Front":
					cont_sp.setChildIndex(target, cont_sp.numChildren - 1);
					break;
				
				case " + Bring Forward":
					cont_sp.setChildIndex(target, cont_sp.getChildIndex(target) + 1);
					break
				
				case " + Send Backward":
					var aa:int = cont_sp.getChildIndex(target);
					if(aa <= 0) {
						return;
					}
					cont_sp.setChildIndex(target, aa - 1);
					break;
				
				case " + Send to Back":
					cont_sp.setChildIndex(target, 0);
					break;
				
				case " + Deselect":
					setTarget(null);
					break;
				
				case " + Reset":
					target.resetImage();
					setTarget(target);
					break;
				
				case " + Remove":
					cont_sp.removeChild(target);
					setTarget(null);
					break;
				
				case " + Remove All":
					cont_sp.removeChildren();
					setTarget(null);
					break;				
				
			}// end switch
			
		}// end cmListener
		
		
	}// end class
}// end package